#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include "RingQueue.hpp"
#include "Task.hpp"

using namespace std;

// 线程数据结构，用于传递参数给线程函数
struct ThreadData {
    RingQueue<Task> *rq;      // 环形队列指针
    std::string threadname;    // 线程名称
};

// 生产者线程函数
void *Productor(void *args) {
    // 将void指针转换为ThreadData指针
    ThreadData *td = static_cast<ThreadData*>(args);
    RingQueue<Task> *rq = td->rq;          // 获取环形队列
    std::string name = td->threadname;      // 获取线程名称
    int len = opers.size();                 // 获取运算符数组长度

    while (true) {
        // 1. 生成随机数据
        int data1 = rand() % 10 + 1;        // 1-10的随机数
        usleep(10);                         // 短暂休眠
        int data2 = rand() % 10;            // 0-9的随机数
        char op = opers[rand() % len];      // 随机选择运算符
        Task t(data1, data2, op);           // 创建任务

        // 2. 将任务放入环形队列
        rq->Push(t);
        cout << "Productor task done, task is : " << t.GetTask() 
             << " who: " << name << endl;

        sleep(1);    // 休眠1秒
    }
    return nullptr;
}

// 消费者线程函数
void *Consumer(void *args) {
    ThreadData *td = static_cast<ThreadData*>(args);
    RingQueue<Task> *rq = td->rq;
    std::string name = td->threadname;

    while (true) {
        // 1. 从环形队列取出任务
        Task t;
        rq->Pop(&t);
       
        // 2. 执行任务并输出结果
        t();    // 执行任务（计算结果）
        cout << "Consumer get task, task is : " << t.GetTask() 
             << " who: " << name 
             << " result: " << t.GetResult() << endl;
    }
    return nullptr;
}

int main() {
    // 初始化随机数种子
    srand(time(nullptr) ^ getpid());
    
    // 创建容量为50的环形队列
    RingQueue<Task> *rq = new RingQueue<Task>(50);

    // 定义线程数组：5个消费者，3个生产者
    pthread_t c[5], p[3];

    // 创建生产者线程
    for (int i = 0; i < 1; i++) {
        ThreadData *td = new ThreadData();
        td->rq = rq;
        td->threadname = "Productor-" + std::to_string(i);

        pthread_create(p + i, nullptr, Productor, td);
    }

    // 创建消费者线程
    for (int i = 0; i < 1; i++) {
        ThreadData *td = new ThreadData();
        td->rq = rq;
        td->threadname = "Consumer-" + std::to_string(i);

        pthread_create(c + i, nullptr, Consumer, td);
    }

    // 等待所有线程结束
    for (int i = 0; i < 1; i++) {
        pthread_join(p[i], nullptr);
    }
    for (int i = 0; i < 1; i++) {
        pthread_join(c[i], nullptr);
    }

    return 0;
}